#if !defined(DATE_TIME_H)
#define DATE_TIME_H

//
//	DateTime.h - time utility
//
//	Author : Tian Bin
//	Date   : 2002.xx.xx
//
//	Copyright (C) 2001 - 2003
//	All rights reserved.
//
// DateTime is defined in this header file.
// DateTime supports a wide range representation of time, formatting, and conversion from and to FILETIME
// the time range is almost not limited. The most precise scale unit is microsecond.

// Modification
// 2005 9 16  ��д��time_unit_t����GetTickCount��FromTickCount���ɳ�Ա���������ԸĶ���ʵ����Add,Inc, Dec, ��Normalize���� --lasher
#include <time.h>
#include <assert.h>
#include <stdio.h>
#include <sstream>
using namespace std;
#include "BasicTypes.h"
#include "string.h"

#ifdef WIN32

#include <olectl.h>

#ifndef PATH_MAX
#define PATH_MAX 512
#endif

#ifndef snprintf
#define snprintf _snprintf
#endif

#else  // !WIN32

#include <sys/time.h>

#endif

struct time_data_t
{
	u_int8_t	time_cat;			//	it is zero for gmt time
	u_int8_t	reseved [15];
};
//ʱ�䵥λ
class TimeUnit
{
public:
	static const int Year			= 0;
	static const int Month			= 1; 
	static const int Week			= 2;
	static const int Day			= 3;
	static const int Hour			= 4;
	static const int Minute			= 5;
	static const int Second			= 6;
	static const int Millisecond	= 7;
	static const int Microsecond	= 8;
};
typedef int time_unit_t;

template < typename T >
inline T make_time_unit (T count, time_unit_t u) throw ()
{
	return (count << 8) + (T)u;
};
template < typename T >
inline time_unit_t get_time_base_unit (T unit) throw ()
{
	return static_cast<time_unit_t>(unit & 0xf);
};
template < typename T >
inline T get_time_mul (T unit) throw ()
{
	return unit >> 8;
};

//��΢��Ϊ��λ��ʱ�����
const int64_t units_per_us = 1;
const int64_t units_per_ms = 1000 * units_per_us;
const int64_t units_per_sec = 1000 * units_per_ms;
const int64_t units_per_min = units_per_sec * 60;
const int64_t units_per_hour = units_per_min * 60;
const int64_t units_per_day = units_per_hour * 24;
const int64_t units_per_week = units_per_day * 7;
//ÿ�º�ÿ����ʱ�����·��Լ������й�ϵ�����Բ��ʺ��ó����ʾ

//�жϸ����������Ƿ�������
template<typename T>
inline bool is_leap(T year)
{
	return ((year & 0x3) == 0) && (((year % 400) == 0) || ((year % 100) != 0));
}



//DateTimeͬʱ����n / d��n % d�����������Ա�֤�õ�������Ϊ��������
template <typename T>
struct posdiv_t
{
	T	quot;
	T	rem;
};

template<typename T>
inline void posdiv (T n, T d, posdiv_t<T>& pd)
{
	pd.quot	= n / d;
	pd.rem	= n % d;
	if (pd.rem < 0)			// n < 0
	{
		if(d > 0)			// n < 0 but d > 0
		{
			--pd.quot;		// quot < 0
			pd.rem += d;
		}
		else				// n and d both are less than zero
		{
			++pd.quot;		// quot > 0
			pd.rem -= d;
		}
	}
	return;
};

inline void div_days (int64_t days, int &y, int &m, int &d)
{
	const int tbl_acc[13] = 
	{
		0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
	};

	posdiv_t<int64_t>	ld;
	posdiv<int64_t> (days, 400*365+100-4+1, ld);			// there are only 97 leap years in every 400 years!

	// first get y
	y = int (ld.quot) * 400;
	if (days < 0)
		--y;

	int y100 = (int) (ld.rem / (100*365+24));
	int y100r = (int) (ld.rem % (100*365+24));
	if (y100 == 4)
	{
		assert(y100r == 0);	
		--y100;
		y100r = 100*365+24;			//the very last day in the whole 400 years!
	}

	int y4 = y100r/(365*4+1);
	int y4r = y100r%(365*4+1);
	int y1 = y4r/365;
	int y1r = y4r%365;
	if (y1 == 4)
	{
		assert(y1r == 0);
		--y1;
		y1r = 365;					// the very last day in 4 years!
	}

	y += y100*100+y4*4+y1+1;		// there are some extra days in y1r, so a plus year is needed

	// modify acc
	const int *acc = tbl_acc;
	int acc_temp[13];
	if (is_leap(y))
	{
		acc = acc_temp;
		acc_temp[0] = tbl_acc[0];
		acc_temp[1] = tbl_acc[1];
		for (int i = 2; i < 13; ++i)
			acc_temp[i] = tbl_acc[i] + 1;
	}

	for (m = 1 ;; ++m)
		if (y1r < acc[m])
		{
			d = y1r-acc[m-1]+1;
			return;
		}
};
//divide the time of "inday" in microsecond unit into separated hour, minute, second, millisecond, and microsecond.
inline void div_inday (int64_t inday, int &h, int &m, int &s, int &ms, int &us)
{
	us = (int) (inday % 1000);
	int count = int (inday / 1000);
	ms = count % 1000, count = count / 1000;
	s = count % 60, count = count / 60;
	m = count % 60, count = count / 60;
	h = count;
};

//	used in "stringa DateTime::Format (int) const"
//
//	NOTES: All timezone fields are not filled
//
enum date_fmt_t
	{
		def_date_fmt		= 0,	//	2004-01-01 04:01:41
		rfc822_date_fmt		= 1,	//	Thu, 01 Jan 2004 04:01:41 GMT
		rfc850_date_fmt		= 2,	//	Thursday, 01-Jan-2004 04:01:41 GMT
		asctime_date_fmt	= 3,	//	Thu Jan  1 04:01:41 2004
		time_fmt_max, 
	};

//
//	gmt time utility
//
class DateTime
{
public:
	DateTime () throw ()
	{
		memset (this, 0, sizeof (*this));
	};
	DateTime (const time_data_t &x) throw ()
	{
		if (x.time_cat != 0)
			assert (false);
		else
			memcpy (this, &x, sizeof (*this));
	};
	DateTime (int y, int M = 1, int d = 1) throw ()
	{
		memset (this, 0, sizeof (*this));
		SetDate (y, M, d);
		SetTime (0, 0, 0);
		SetTime (0, 0);
	};
	DateTime (int y, int M, int d, 
		int H, int m = 0, int s = 0, int ms = 0, int us = 0) throw ()
	{
		memset (this, 0, sizeof (*this));
		SetDate (y, M, d);
		SetTime (H, m, s);
		SetTime (ms, us);
	};
	DateTime (const char *sz) throw ()
	{
		operator = (sz);
	};
	DateTime (const wchar_t *sz) throw ()
	{
		operator = (sz);
	};
	DateTime(int64_t dt) throw()
	{
		FromTickCount(dt);
	}
#ifdef _WIN32
	DateTime (const ::FILETIME &ft) throw ()
	{
		int H, m, s;
		int ms, us;
		int64_t	i64 = *(int64_t*)&ft - 116444736000000000I64;			//I64 is a sufix for 64 bits integer
		//FILETIME represents the number of 100 nanoseconds intervals elapsed since January 1th, 1601
		i64 /= 10,		us = (int) (i64 % 1000);
		i64 /= 1000,	ms = (int) (i64 % 1000);
		i64 /= 1000,	s = (int) (i64 % 60);
		i64 /= 60,		m = (int) (i64 % 60);
		i64 /= 60,		H = (int) (i64 % 24);
		i64 /= 24;
		reserved1 = 0;
		FromJulianDayNumber (2440588 + i64);
		SetTime (H, m, s);
		SetTime (ms, us);
	};
	DateTime (const ::FILETIME *ft) throw ()
	{
		int H, m, s;
		int ms, us;
		int64_t	i64 = *(int64_t*)ft - 116444736000000000I64;
		i64 /= 10,		us = (int) (i64 % 1000);
		i64 /= 1000,	ms = (int) (i64 % 1000);
		i64 /= 1000,	s = (int) (i64 % 60);
		i64 /= 60,		m = (int) (i64 % 60);
		i64 /= 60,		H = (int) (i64 % 24);
		i64 /= 24;
		reserved1 = 0;
		FromJulianDayNumber (2440588 + i64);
		SetTime (H, m, s);
		SetTime (ms, us);
	};
	DateTime& operator=(const ::FILETIME& ft) throw()
	{
		int H, m, s;
		int ms, us;
		int64_t	i64 = *(int64_t*)&ft - 116444736000000000I64;			//I64 is a sufix for 64 bits integer
		//FILETIME represents the number of 100 nanoseconds intervals elapsed since January 1th, 1601
		i64 /= 10,		us = (int) (i64 % 1000);
		i64 /= 1000,	ms = (int) (i64 % 1000);
		i64 /= 1000,	s = (int) (i64 % 60);
		i64 /= 60,		m = (int) (i64 % 60);
		i64 /= 60,		H = (int) (i64 % 24);
		i64 /= 24;
		reserved1 = 0;
		FromJulianDayNumber (2440588 + i64);
		SetTime (H, m, s);
		SetTime (ms, us);
		return *this;
	}
#else
	DateTime(const timeval& tv)
	{
		this->operator=(tv);
	}
	DateTime(const timespec& ts)
	{
		this->operator=(ts);
	}
	DateTime& operator=(const timeval& tv)
	{
		// timeval contains seconds and us since the start of the UNIX epoch, on midnight UTC on January 1, 1970.
		FromTickCount(tv.tv_sec * 1000000LL + tv.tv_usec + 62135596800000000LL);
		return *this;
	}
	DateTime& operator=(const timespec& ts)
	{
		// timeval contains seconds and us since the start of the UNIX epoch, on midnight UTC on January 1, 1970.
		FromTickCount(ts.tv_sec * 1000000LL + ts.tv_nsec / 1000LL + 62135596800000000LL);
		return *this;
	}
#endif

	bool Parse(istream& istr) throw()
	{
		if(!istr)
			return false;
		if(istr.get() == '#')
		{
			char sz[10];
			istr.get(sz, 10);
			sz[9] = 0;
			if(!istr)
				return false;
			if(strncmp(sz, "-@min-gmt", 9) == 0)
			{
				*this = MinTime();
				return true;
			}
			else if(strncmp(sz, "-@max-gmt", 9) == 0)
			{
				*this = MaxTime();
				return true;
			}
			else if(strncmp(sz, "-@bad-gmt", 9) == 0)
			{
				*this = BadTime();
				return true;
			}
			return false;
		}
		istr.unget();

		int y = 0, M = 0, d = 0;
		int H = 0, m = 0, s = 0;
		int ms = 0, us = 0;
		char c;

		istr >> y >> c;
		if(!istr || (c != '/' && c !='-'))
			return false;
		istr >> M >> c;
		if(!istr || (c != '/' && c !='-'))
			return false;
		istr >> d;
		if(!istr)
			return false;
		istr >> H >> c >> m >> c >> s >> ms >> us;
		if(!istr)
		{
			H = m = s = ms = us = 0;
			istr.clear();
		}
		if (y >= 292278 || y <= -292278)
			return false;
		if (y == 1 && M == 1 && d == 1					//why return in this case
			&& H == 0 && m == 0 && s == 0 
			&& ms == 0 && us == 0)
			return false;
		SetDate (y, M, d);
		SetTime (H, m, s);
		SetTime (ms, us);
		return true;
	}
	const DateTime& operator = (const char *sz) throw ()
	{
		if (strncmp (sz, "#-@min-gmt", 10) == 0)
			return *this = MinTime ();

		if (strncmp (sz, "#-@max-gmt", 10) == 0)
			return *this = MaxTime ();

		memset (this, 0, sizeof (*this));

		if (strncmp (sz, "#-@bad-gmt", 10) == 0)
			return *this = BadTime();

		int y = 0, M = 0, d = 0;
		int H = 0, m = 0, s = 0;
		int ms = 0, us = 0;
		sscanf (sz, "%d/%d/%d %d:%d:%d %d %d", 
				&y, &M, &d, &H, &m, &s, &ms, &us);
		if (y >= 292278 || y <= -292278)
			return *this;
		if (y == 1 && M == 1 && d == 1					//why return in this case
			&& H == 0 && m == 0 && s == 0 
			&& ms == 0 && us == 0)
			return *this;
		SetDate (y, M, d);
		SetTime (H, m, s);
		SetTime (ms, us);
		return *this;
	};
	bool IsValid () const throw ()
	{
		return (internal1 & 7) == 7;
	}

	//
	//	member access
	//
	bool GetDate (int &y, int &M, int &d) const throw ()
	{
		if ((internal1 & 1) == 0)
			return false;
		y = year, M = month, d = day;
		return true;
	};
	bool GetTime (int &H, int &m, int &s) const throw ()
	{
		if ((internal1 & 2) == 0)
			return false;
		H = hour, m = minute, s = second;
		return true;
	};
	bool GetTime (int &ms, int &us) const throw ()
	{
		if ((internal1 & 4) == 0)
			return false;
		ms = this->ms, us = this->us;
		return true;
	};
	bool SetDate (int y, int M, int d) throw ()
	{
		if (!Check (y, M, d))
			return false;
		year = y, month = int8_t (M), day = int8_t (d);
		internal1 |= 1;
		return true;
	};
	bool SetTime (int H, int m, int s) throw ()
	{
		assert (H >= 0 && H < 24);
		assert (m >= 0 && m < 60);
		assert (s >= 0 && s < 60);
		if (H < 0 || H >= 24 || m < 0 || m >= 60 || s < 0 || s >= 60)
			return false;
		hour = int8_t (H), minute = int8_t (m), second = int8_t (s);
		internal1 |= 2;
		return true;
	};
	bool SetTime (int ms, int us) throw ()
	{
		assert (ms >= 0 && ms < 1000);
		assert (us >= 0 && us < 1000);

		if (ms < 0 || ms >= 1000 || us < 0 || us >= 1000)
			return false;
		this->ms = int16_t (ms), this->us = int16_t (us);
		internal1 |= 4;
		return true;
	};

	int GetYear() const
	{
		return year;
	}
	int GetMonth()const
	{
		return month;
	}
	int GetDay()const
	{
		return day;
	}
	int GetHour()const
	{
		return hour;
	}
	int GetMinute()const
	{
		return minute;
	}
	int GetSecond()const
	{
		return second;
	}
	int GetMillisecond()const
	{
		return ms;
	}
	int GetMicrosecond()const
	{
		return us;
	}

	/*
	 * GetJulianDayNumber - Gregorian Date to Julian Day Number
	 *
	 *   SEE: http://vsg.cape.com/~pbaum/date/jdimp.htm
	 *
	 * the result is limited by word size
	 */
	int64_t GetJulianDayNumber () const
	{
		int Y = year, M = month, D = day;
		static int xxx [] =
		{ 306, 337, 0, 31, 61, 92, 122, 153, 184, 214, 245 };
		long long jdn;
		assert (M >= 1 && M<= 12);
		Y -= (M < 3);
		jdn = D + xxx [M-1] + 365 * Y + 1721119;
		if (Y < 0)
		{
			Y = -1 - Y;
			jdn += - Y/4 + Y/100 - Y/400 - 1;
		}
		else
			jdn += Y/4 - Y/100 + Y/400;
		return jdn;
	};

	/*
	* FromJulianDayNumber - Julian Day Number to Gregorian Date
	*
	*   SEE: http://vsg.cape.com/~pbaum/date/injdimp.htm
	*
	* the result is limited by word size
	*/
	void FromJulianDayNumber (int64_t jdn)
	{
		int64_t Z, H, A, B, C, y;

		Z = jdn - 1721119;
		H = 100 * Z - 25;

		if (H < 0)
			B = A = -1 - (-1 - H) / 3652425;
		else
			B = A = H / 3652425;

		if (A < 0)
			B -= -1 - (-1 - A) / 4;
		else
			B -= A / 4;

		y = 100 * B + H;

		if (y < 0)
			year = (int) (-1 - (-1 - y)/36525);
		else
			year = (int)(y / 36525);

		C = B + Z - 365ll* year;
		if (year < 0)
			C -= -1 - (-1 - year)/4;
		else
			C -= year/4;

		month = int8_t((5 * C + 456) / 153);

		day = (int8_t)(C - (153 * month - 457)/5);
		if (month > 12) ++year, month -= 12;
		internal1 |= 1;
	};

	//
	// return value is in [0, 7), 0 stand for Sunday
	//
	int Week () const throw ()
	{
		return (int)((GetJulianDayNumber () + 1)%7);
	};

	//
	//	make the string Format
	//
	const char *Format (char *buf) const throw ()
	{
		if (IsMin ())
			return strcpy (buf, "#-@min-gmt");
		if (IsMax ())
			return strcpy (buf, "#-@max-gmt");
		if (!IsValid ())
			return strcpy (buf, "#-@bad-gmt");
		snprintf(buf, 0x100, "%d/%02d/%02d %02d:%02d:%02d %03d %03d", 
			year, month, day, hour, minute, second, ms, us);
		return buf;
	}

	string ToString() const throw()
	{
		char buf[80];
		return Format(buf);
	}

	string ToShortString() const
	{
		ostringstream ostr;
		if(IsMin())
			return "#-@min-gmt";
		if(IsMax())
			return "#-@max-gmt";
		if(!IsValid())
			return "#-@bad-gmt";
		char buf[100];
		snprintf(buf, 100, "%d/%02d/%02d %02d:%02d:%02d", year, month, day, hour, minute, second);
		return buf;
	}
	bool IsMin() const throw ()
	{
		if (IsValid ())
			return false;
		return (internal2 & 0x80) == 0;
	};
	bool IsMax() const throw ()
	{
		if (IsValid ())
			return false;
		return (internal2 & 0x80) == 0x80;
	};
	bool IsBad() const throw()
	{
		if(IsValid())
			return false;
		return (internal2 & 0x01) == 0x01;
	}
	//
	//	Compare
	//
	bool operator == (const DateTime& x) const throw ()
	{
		if (IsValid () ^ x.IsValid ())
			return false;
		if (IsValid ())
			return year == x.year && month == x.month && day == x.day
				&& hour == x.hour && minute == x.minute && second == x.second
				&& ms == x.ms && us == x.us;
		return internal2 == x.internal2;
	};
	bool operator != (const DateTime &x) const throw ()
	{
		return !operator == (x);
	};
	bool operator < (const DateTime& x) const throw ()
	{
		if(IsBad() || x.IsBad())		// bad С��һ��
		{
			return IsBad() && !x.IsBad();
		}
		if (IsMax () || x.IsMin ())
			return false;

		if (IsMin ())
			return !x.IsMin ();

		if (x.IsMax ())
			return !IsMax ();

		if(year != x.year)
			return year < x.year;
		else if(month != x.month)
			return month < x.month;
		else if(day != x.day)
			return day < x.day;
		else if(hour != x.hour)
			return hour < x.hour;
		else if(minute != x.minute)
			return minute < x.minute;
		else if(second != x.second)
			return second < x.second;
		else if(ms != x.ms)
			return ms < x.ms;
		else
			return us < x.us;
	};
	bool operator >= (const DateTime &x) const throw ()
	{
		return !operator < (x);
	};
	bool operator > (const DateTime &x) const throw ()
	{
		return x.operator < (*this);
	};
	bool operator <= (const DateTime &x) const throw ()
	{
		return !operator > (x);
	};
	int Compare(const DateTime& x) const throw()
	{
		if(IsBad() || x.IsBad())		// bad С��һ��
		{
			if(IsBad() == x.IsBad())
				return 0;
			return IsBad() ? -1 : 1;
		}
		if (IsMax ())
			return x.IsMax() ? 0 : 1;

		if (IsMin ())
			return x.IsMin() ? 0 : -1;

		if(x.IsMax())
			return -1;

		if(x.IsMin())
			return 1;

		if(year != x.year)	return year - x.year;
		if(month != x.month) return month - x.month;
		if(day != x.day) return day - x.day;
		if(hour != x.hour) return hour - x.hour;
		if(minute != x.minute) return minute - x.minute;
		if(second != x.second) return second - x.second;
		if(ms != x.ms) return ms - x.ms;
		if(us != x.us) return us - x.us;
		return 0;
	}


	//
	//	get the current time
	//
	static const DateTime Now() throw ()
	{
#ifdef _WIN32
		FILETIME ft;
		::GetSystemTimeAsFileTime (&ft);
		return DateTime (ft);
#else
		struct timeval	tv;
		struct timezone	tz;
		gettimeofday (&tv, &tz);
		return DateTime(tv);
#endif
	};
	static bool Check(int y, int M, int d) throw ()
	{
		int a = (M-14)/12;
		DateTime tm;
		tm.FromJulianDayNumber ((1461*(int64_t(y)+4800+a))/4		//confused formular
			+ (367*(M-2-12*(a)))/12
			- (3*((int64_t(y)+4900+a)/100))/4
			+ d-32075);;
		int _y, _M, _d;
		tm.GetDate (_y, _M, _d);
		return y == _y && M == _M && d == _d;
	};
	static const DateTime &MinTime() throw ()
	{
		static const time_data_t _min_time_data = { 0, 0, 0, };
		static const DateTime _min_time(_min_time_data);
		return _min_time;
	};
	static const DateTime &MaxTime() throw ()
	{
		static const time_data_t _max_time_data = { 0, 0, 0x80, };
		static const DateTime _max_time(_max_time_data);
		return _max_time;
	};
	static const DateTime &BadTime() throw()
	{
		static const time_data_t _bad_time_data = {0, 0, 0x01, };
		static const DateTime _bad_time(_bad_time_data);
		return _bad_time;
	}
	int64_t GetTickCount() const throw()
	{
		static const int mdy1 [] =
		{
			31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
		};
		static const int mdy2 [] = 
		{
			31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
		};
		const int *mdy = mdy1;
		//the accumulated number of day in year on month boundaries
		static const int acc1 [] =
		{
			0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
		};
		static const int acc2[] = 
		{
			0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335
		};
		const int *acc = acc1;

		int	y, M, d;

		GetDate (y, M, d);
		--M, --d;
		posdiv_t<int64_t> qr;
		posdiv<int64_t>(M, 12, qr);
		y += (int)qr.quot;
		M = (int)qr.rem;

		if(is_leap(y))
		{
			mdy = mdy2;
			acc = acc2;
		}

		if (y > 0)
			--y;

		int64_t days = y*365ll+y/4-y/100+y/400+acc[M]+d;

		int64_t ret = days*units_per_day + us + ms*1000ll
			+second*units_per_sec
			+minute*units_per_min
			+hour*units_per_hour;
		return ret;
	}
	void FromTickCount (int64_t i64) throw()
	{
		posdiv_t<int64_t> ld;
		int y, M, d, H, m, s, _ms, _us;

		posdiv<int64_t> (i64, units_per_day, ld);
		div_days (ld.quot, y, M, d);
		div_inday (ld.rem, H, m, s, _ms, _us);
		SetDate(y, M, d);
		SetTime(H, m, s);
		SetTime(_ms, _us);			
	}
	void Normalize() throw()
	{
		FromTickCount(GetTickCount());
	}
	const DateTime& Add (time_unit_t unit, int64_t count) throw ()
	{
        switch(unit)
		{
		case TimeUnit::Year:
			year += (int32_t)count;
			Normalize();
			break;
		case TimeUnit::Month:
			{
				int64_t m = month + count - 1;
				posdiv_t<int64_t> qr;
				posdiv<int64_t>(m, 12, qr);
				month = (int8_t)qr.rem + 1;
				year += (int32_t)qr.quot;
				Normalize();
			}
			break;
		case TimeUnit::Day:
			FromTickCount(GetTickCount() + units_per_day * count);
			break;
		case TimeUnit::Hour:
			FromTickCount(GetTickCount() + units_per_hour * count);
			break;
		case TimeUnit::Minute:
			FromTickCount(GetTickCount() + units_per_min * count);
			break;
		case TimeUnit::Second:
			FromTickCount(GetTickCount() + units_per_sec * count);
			break;
		case TimeUnit::Millisecond:
			FromTickCount(GetTickCount() + units_per_ms * count);
			break;
		case TimeUnit::Microsecond:
			FromTickCount(GetTickCount() + units_per_us * count);
			break;
		case TimeUnit::Week:
			FromTickCount(GetTickCount() + units_per_week * count);
			break;
		default:
			assert(false);
		}
		return *this;
	}
	const DateTime& Inc(time_unit_t unit) throw ()
	{
        return Add(unit, 1);
	}
	const DateTime& Dec(time_unit_t unit) throw ()
	{
		return Add(unit, -1);
	}
	void ToUTCTime()
	{
		if(!IsValid())
			return;
		tzset();
		Add(TimeUnit::Second, timezone);
	}
	void ToLocalTime()
	{
		if(!IsValid())
			return;
		tzset();
		Add(TimeUnit::Second, -timezone);
	}
public:
	static const DateTime Null;
protected:
	u_int8_t	reserved1;	//	always be zero
	u_int8_t	internal1;	//	for internal use
	u_int8_t	internal2;	//	for internal use
	int8_t	second;
	int8_t	minute;
	int8_t	hour;
	int8_t	day;
	int8_t	month;
	int32_t	year;
	int16_t	ms;
	int16_t	us;
};

inline istream& operator>>(istream& istr, DateTime& t)
{
	if(!t.Parse(istr))
		istr.setstate(ios::failbit);
	return istr;
}
inline ostream& operator<<(ostream& ostr, const DateTime& t)
{
	char sz[0x80];
	t.Format(sz);
	ostr << sz;
	return ostr;
}


typedef struct TimeSpan
{
public:
	DateTime begin;
	DateTime end;
	TimeSpan()
	{
	}
	TimeSpan(const DateTime& b, const DateTime& e)
	{
		begin = b;
		end = e;
	}
	bool operator == (const TimeSpan& ts) const
	{
		return ts.begin == begin && ts.end == end;
	}
	bool operator != (const TimeSpan& ts) const
	{
		return !this->operator==(ts);
	}
	//���������Ĵ�С�Ƚϣ�begin����(ֻ��Ϊ�˹涨һ��˳������ʵ������)
	bool operator < (const TimeSpan& ts) const
	{
		int cmp = begin.Compare(ts.begin);
		if(cmp < 0)
			return true;
		else if(cmp == 0)
			return end.Compare(ts.end) < 0;
		else
			return false;
	}
	bool Parse(const string& str)
	{
		istringstream istr(str);
		istr >> begin;
		char c;
		istr >> c;
		istr >> end;
		return !istr.fail();
	}
	string ToString() const
	{
		ostringstream ostr;
		ostr << begin << ',' << end;
		return ostr.str();
	}
}TimeSpan;

inline istream& operator>>(istream& istr, TimeSpan& ts)
{
	istr >> ts.begin;
	char c;
	istr >> c;
	istr >> ts.end;
	return istr;
}
inline ostream& operator<<(ostream& ostr, const TimeSpan& ts)
{
	ostr << ts.begin << ',' << ts.end;
	return ostr;
}

#endif // !defined(DATE_TIME_H)

